<?php
/**********************************************************************************
WIKINDX: Bibliographic Management system.
Copyright (C)

This program is free software; you can redistribute it and/or modify it under the terms
of the GNU General Public License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program;
if not, write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

The WIKINDX Team 2006
sirfragalot@users.sourceforge.net
**********************************************************************************/
/*
* IMPORTCOMMON class
*
* Provides methods common to the import scripts.
* @author Mark Grimshaw
* @version 1
* $Header: /cvsroot/wikindx/wikindx3/core/file/import/IMPORTCOMMON.php,v 1.33 2007/10/21 17:04:39 sirfragalot Exp $
*/
class IMPORTCOMMON
{
// Constructor
	function IMPORTCOMMON($db)
	{
		$this->db = $db;
		include_once("core/html/HTML.php");
		include_once("core/messages/LANGUAGE.php");
		$this->noSortArray = LANGUAGE::noSort();
		include_once("core/html/FORM.php");
		include_once("core/html/HTML.php");
		$this->html = new HTML();
		include_once("core/html/MISC.php");
		include_once("core/collection/COLLECTION.php");
		$this->collection = new COLLECTION($this->db);
		include_once("core/publisher/PUBLISHER.php");
		$this->publisher = new PUBLISHER($this->db);
		include_once("core/creator/CREATOR.php");
		$this->creator = new CREATOR($this->db);
		include_once("core/keyword/KEYWORD.php");
		$this->keyword = new KEYWORD($this->db);
		include_once("core/session/SESSION.php");
		$this->session = new SESSION();
		include_once("core/messages/MESSAGES.php");
		$this->messages = new MESSAGES();
		include_once("core/messages/ERRORS.php");
		$this->errors = new ERRORS();
		include_once("core/messages/UTF8.php");
		$this->utf8 = new UTF8();
		$this->index = 0;
	}
/*
* titleExists - check if a title already exists in the database.
* We check on title, resource type and, if it exists, primary creator surname.
* 
* @author Mark Grimshaw
* @param string $title - import title
* @param string $creatorSurname - primary creator's surname (may be FALSE)
* @param string $type - import resource type
* @return BOOLEAN
*/
	function titleExists($title, $creatorSurname, $type)
	{
		$title = trim($title);
		$join = $condition2 = FALSE;
		if($creatorSurname)
		{
			$recordset = $this->db->select(array('WKX_creator'), array('id'), 
				" WHERE " . $this->db->formatfield('surname') . "=" . 
				$this->db->tidyInput($creatorSurname));
			while($row = $this->db->loopRecordSet($recordset)) // May be more than one creator with same surname
				$ids[] = $row['id'];
			if(isset($ids))
			{
				$join = " LEFT JOIN " . $this->db->formatTable("WKX_resource_creator") . " ON " .
					$this->db->formatField("WKX_resource_creator.id") . "=" . 
					$this->db->formatField("WKX_resource.id");
// NB MySQL bug: http://bugs.mysql.com/bug.php?id=2047 -- append comma temporarily
				foreach($ids as $id)
					$condition[] = "(" . $this->db->tidyInput($id) . ", CONCAT(" . 
					$this->db->formatField("creator1") . ", ','))";
				$condition2 = " AND (FIND_IN_SET" . join(" OR FIND_IN_SET", $condition) . ")";
			}
			else
				return FALSE;
		}
		$condition1 = " WHERE " . $this->db->concat(
			array(
				"CASE WHEN " . $this->db->formatField('noSort') . " IS NULL" . 
				" THEN " . $this->db->tidyInputNoTrim('') . 
				" ELSE " . 
					$this->db->concat(array($this->db->formatField('noSort'), 
					$this->db->tidyInputNoTrim(' '))) . 
				" END", 
				" CASE WHEN " . $this->db->formatField('subtitle') . " IS NULL" . 
				" THEN " . $this->db->formatField('title') . 
				" ELSE " . 
					$this->db->concat(array($this->db->formatField('title'), 
					$this->db->tidyInputNoTrim(': '), $this->db->formatField('subtitle'))) . 
				" END"
			)) . "=" . $this->db->tidyInput($title) . 
			" AND " . $this->db->formatField('type') . "=" . $this->db->tidyInput($type);
		$fields = $condition2 ? array('title', 'creator1') : array('title');
		$recordset = $this->db->select(array('WKX_resource'), $fields, $join . $condition1 . $condition2);
		if($this->db->numRows($recordset))
			return TRUE;
		return FALSE;
	}
/* select box for adding to user bibliography
*
* @author Mark Grimshaw
*
* @return FALSE or select box string
*/
	function bibliographySelect()
	{
		if(!$this->session->issetVar('mywikindx_bibliographies'))
			return FALSE;
		$bibs = unserialize($this->session->getVar('mywikindx_bibliographies'));
// Add 'ignore' to list
		$temp[0] = $this->messages->text("misc", "ignore");
		foreach($bibs as $key => $value)
			$temp[$key] = $value;
		$bibs = $temp;
		$useBib = $this->session->getVar('mywikindx_bibliography_use');
		if($this->session->issetVar('mywikindx_bibliography_use') && array_key_exists($useBib, $bibs))
		{
			$selectedArray[] = $useBib;
			return FORM::selectedBoxValueMultiple(
				$this->messages->text('resources', "addNewResourceToBib"), 
				"import_bib_ids", $bibs, $selectedArray, "6") . 
				MISC::br() . $this->messages->text("hint", "multiples");
		}
		else
			return FORM::selectFBoxValueMultiple(
				$this->messages->text('resources', "addNewResourceToBib"), "import_bib_ids", $bibs, "6") . 
				MISC::br() . $this->messages->text("hint", "multiples");
	}
/* add import to user bibliographies
*
* @author Mark Grimshaw
*/
	function bibliographyAdd($addIdsArray)
	{
		if(!$bibliographies = $this->session->getVar('import_bib_ids'))
			return;
		$bibs = explode(',', $bibliographies);
		$newIds = join(',', $addIdsArray);
		foreach($bibs as $bibId)
		{
			if(!$bibId)	// ID 0 == IGNORE
				continue;
			$bibIds[] = $bibId;
		}
		if(!isset($bibIds))
			return;
// cleared to write to user bibliographies.
		foreach($bibIds as $bibId)
		{
			$recordset = $this->db->select(array('WKX_user_bibliography'), array('bibliography'), 
				" WHERE " . $this->db->formatfield('id') . "=" . $this->db->tidyInput($bibId));
// bibliography is a comma-separated list of unique resource ids.
			$dbBibsRow = $this->db->fetchOne($recordset);
			if(!$dbBibsRow)
				$updateArray = array('bibliography' => $newIds);
			else
				$updateArray = array('bibliography' => $dbBibsRow . ',' . $newIds);
			$this->db->update('WKX_user_bibliography', $updateArray, 
				" WHERE " . $this->db->formatfield('id') . "=" . $this->db->tidyInput($bibId));
		}
// Update session
		include_once("core/user/USER.php");
		$user = new USER($this->db);
		$user->grabBibliographies();
	}
/* writeCreatorTable - write creators to WKX_creator table
*
* @author Mark Grimshaw
*
* @param $firstname
* @param $initials (space-delimited)
* @param $prefix (von, della, de etc.)
* @param $surname
* @return lastAutoId - suitable for inserting into WKX_resource_creator `creator1`, `creator2` etc. field
*/
	function writeCreatorTable($firstname, $initials, $prefix, $surname)
	{
		if($id = $this->creator->checkExists($surname, $firstname, $initials, $prefix))
			return $id;
		if($surname)
		{
			$fields[] = "surname";
			$values[] = $surname;
		}
		if($firstname)
		{
			$fields[] = "firstname";
			$values[] = $firstname;
		}
		if($initials)
		{
			$fields[] = "initials";
			$values[] = $initials;
		}
		if($prefix)
		{
			$fields[] = "prefix";
			$values[] = $prefix;
		}
		$this->db->insert('WKX_creator', $fields, $values);
		$id = $this->db->lastAutoId('WKX_creator');
// Add new name to current list
		$this->creator->dbNames[$id] = 
			$this->utf8->smartUtf8_encode(str_replace(' ', '', $surname . $firstname . $initials . $prefix));
		return $id;
	}
/*
* writeCollectionTable - write WKX_collection table if necessary.
* @author Mark Grimshaw
*
* @param $title - title of collection (e.g. journal title, newspaper, book title etc.)
* @param $short - abbreviated title of collection
* @param $wkType - the WIKINDX resource type
* @return collection ID suitable for inserting into WKX_resource_misc `collection` field
*/
	function writeCollectionTable($collection, $publisherId, $confPublisherId = FALSE)
	{
		$this->index++;
		$collection = array_map(array($this, "encodeUTF8"), $collection);
		return $this->collection->writeCollectionTable($collection, $publisherId, $confPublisherId);
	}
	function encodeUTF8($element)
	{
		return $this->utf8->smartUtf8_encode($element);
	}
/*
* writePublisherTable - write WKX_publisher table if necessary.
* @author Mark Grimshaw
*
* @param $name - name of publisher
* @param $location - location of publisher
* @param $wkType - the WIKINDX resource type
* @return ID suitable for inserting into WKX_resource_misc `publisher` field
*/
	function writePublisherTable($name, $location, $wkType)
	{
		if($wkType == 'proceedings_article')
		{
			$publisher = array('type' => $wkType, 'confPublisherName' => $name, 
				'confPublisherLocation' => $location);
			$id = $this->publisher->writePublisherTable($publisher, FALSE, TRUE);
		}
		else
		{
			$publisher = array('type' => $wkType, 'publisherName' => $name, 'publisherLocation' => $location);
			$id = $this->publisher->writePublisherTable($publisher);
		}
		return $id;
	}
/*
* writeResourceKeywordTable - write WKX_resource_keyword table and, if necessary, WKX_keyword table
* @author Mark Grimshaw
*
* @param $keywords - string of keywords from import file
* @param $resourceId - INT of this resource's id from WKX_resource table
* @param $separator - keyword separator string
*/
	function writeResourceKeywordTable($keywords, $resourceId, $separator)
	{
		if($separator == 0)
			$keywords = preg_split("/,/", trim($keywords));
		else if($separator == 1)
			$keywords = preg_split("/;/", trim($keywords));
		else if($separator == 2)
			$keywords = preg_split("/;|,/", trim($keywords));
		else
			$keywords = preg_split("/ /", trim($keywords));
		foreach($keywords as $keyword)
		{
			$keyword = trim($keyword);
			if(!$keyword)
				continue;
			$tempK[] = $keyword;
		}
		if(!isset($tempK))
			return;
		$keywords = array_unique($tempK);
		foreach($keywords as $keyword)
		{
			if($id = $this->keyword->checkExists($keyword))
				$keywordIds[] = $id;
			else
				$keywordInserts[] = $keyword;
		}
		if(isset($keywordInserts))
		{
			foreach($keywordInserts as $insert)
			{
				$keyword = $this->utf8->utf8_strtolower($this->utf8->smartUtf8_encode($insert));
				if(($id = array_search($keyword, $this->keyword->dbKeywords)) === FALSE)
				{
					$this->db->insert('WKX_keyword', array('keyword'), array($insert));
					$id = $this->db->lastAutoID('WKX_keyword');
// Add new keyword to current list
					$this->keyword->dbKeywords[$id] = $keyword;
				}
				$keywordIds[] = $id;
			}
		}
		if(isset($keywordIds))
		{
			$string = join(",", $keywordIds);
			$this->db->insert('WKX_resource_keyword', array('id', 'keywords'), 
				array($resourceId, $string));
		}
	}
	
/* splitTitle - split title into WIKINDX component parts (noSort, title : subtitle)
*
* @author Mark Grimshaw
*
* @param $title
* @return $noSort
* @return $title
* @return $subtitle
*/
	function splitTitle($title)
	{
		include_once("core/session/SESSION.php");
		$session = new SESSION();
		$noSort = $subtitle = FALSE;
		$split = $session->getVar('import_titleSubtitleSeparator');
		if($split) // split title and subtitle
		{
			switch($split)
			{
				case 1: 
					$split = ':';
					break;
				case 2: 
					$split = ';';
					break;
				case 3: 
					$split = '[.!?]';
					break;
				case 4: 
					$split = '--';
					break;
				case 5: 
					$split = '-';
					break;
			}
			$array = preg_split("/$split\s+/", $title, 2);
			if(sizeof($array) > 1)
			{
				$title = trim(array_shift($array));
				$subtitle = trim(implode('', $array));
			}
			else
				$title = trim($array[0]);
		}
		foreach($this->noSortArray as $pattern)
		{
			if(preg_match("/^($pattern)\s(.*)/i", $title, $matches))
			{
				$title = trim($this->html->removeNl($matches[2]));
				$noSort = trim($this->html->removeNl($matches[1]));
				break;
			}
		}
		return array($noSort, $title, $subtitle);
	}
/*
* createDir - create a directory (if it doesn't exist) based on session ID
* 
* @author Mark Grimshaw
*
* @param $dirName - directory name to make (usually "files/" . session_id() . "/")
* @return $dh directory handle or FALSE if unable to create directory
*/
	function createDir($dirName)
	{
		if(!$dh = @opendir($dirName))
		{
			if(!mkdir($dirName))
				return FALSE;
			else
				$dh = @opendir($dirName);
		}
		return $dh;
	}
/*
* printDuplicates - Print a list of discarded duplicates.
* 
* @author Mark Grimshaw
*
* @param INT $numDiscarded - num. duplicates discarded
* @param ARRAY $titlesDiscarded - authors + titles of discarded duplicates
* @return browser print string.
*/
	function printDuplicates($numDiscarded, $titlesDiscarded)
	{
		include_once("core/messages/MESSAGES.php");
		$messages = new MESSAGES();
		if(($numDiscarded <= 50) && !empty($titlesDiscarded))
		{
			$reject = $messages->text("import", "discarded", " " . $numDiscarded);
			foreach($titlesDiscarded as $title)
				$reject .= MISC::br() . $title;
			return MISC::p($reject);
		}
		return MISC::p($messages->text("import", "discarded", " " . $numDiscarded));
	}
/*
* Email notification
*
* @author Mark Grimshaw
*
* param array of resource ids that have been added
*/
	function notify($addedResourceIds)
	{
		include_once("core/notify/NOTIFY.php");
		$notify = new NOTIFY($this->db);
		$notify->email($addedResourceIds, TRUE); // TRUE for new resource(s)
	}
/*
* Select box for specifying keyword separation character in source bibliography
*/
	function keywordSeparator()
	{
		include_once("core/messages/MESSAGES.php");
		$messages = new MESSAGES();
		include_once("core/session/SESSION.php");
		$session = new SESSION();
		include_once("core/html/FORM.php");
		$sessVar = $session->issetVar('import_keywordSeparator') ? 
			$session->getVar('import_keywordSeparator') : FALSE;
		$array = array(
			$messages->text('misc', 'keywordImport1'),
			$messages->text('misc', 'keywordImport2'),
			$messages->text('misc', 'keywordImport3'),
			$messages->text('misc', 'keywordImport4'),
			);
		if($sessVar)
			return FORM::selectedBoxValue($messages->text('misc', 'keywordImport'), 
				'import_keywordSeparator', $array, $sessVar, 4);
		else
			return FORM::selectFBoxValue($messages->text('misc', 'keywordImport'), 
				'import_keywordSeparator', $array, 4);
	}
/*
* Select box for specifying title/subtitleseparation character in source bibliography
*/
	function titleSubtitleSeparator()
	{
		include_once("core/messages/MESSAGES.php");
		$messages = new MESSAGES();
		include_once("core/session/SESSION.php");
		$session = new SESSION();
		include_once("core/html/FORM.php");
		$sessVar = $session->getVar('import_titleSubtitleSeparator');
		$array = array(
			$messages->text('misc', 'titleSubtitleSeparator1'),
			$messages->text('misc', 'titleSubtitleSeparator2'),
			$messages->text('misc', 'titleSubtitleSeparator3'),
			$messages->text('misc', 'titleSubtitleSeparator4'),
			$messages->text('misc', 'titleSubtitleSeparator5'),
			$messages->text('misc', 'titleSubtitleSeparator6'),
			);
		if($sessVar)
			return FORM::selectedBoxValue($messages->text('misc', 'titleSubtitleSeparator'), 
				'import_titleSubtitleSeparator', $array, $sessVar, 6);
		else
			return FORM::selectedBoxValue($messages->text('misc', 'titleSubtitleSeparator'), 
				'import_titleSubtitleSeparator', $array, 1, 6);
	}
/**
* promptFieldNames - print field name mapping to browser as an intermediate stage
* 
* @author Mark Grimshaw
*/
	function promptFieldNames($entries, $inputTypes, $vars, $map, $invalidFieldNames, $strings, $parent)
	{
// Do some system management
		include_once("core/file/FILE.php");
		$file = new FILE($this->db);
		$file->tidyFiles();
// Write entries as serialised array temporarily to files/
		$serArray = base64_encode(serialize($entries));
		$fileName = sha1($serArray);
		$fullFileName = 'files/' . $fileName;
		if(!$fp = fopen("$fullFileName", "w"))
			$parent->badInput($this->errors->text("file", "write", ": $fileName"));
		if(!fputs($fp, $serArray))
			$parent->badInput($this->errors->text("file", "write", ": $fileName"));
		fclose($fp);
// Write filename to session
		$this->session->setVar("import_fileNameEntries", $fileName);
// Write $this->strings as serialised array temporarily to files/
		if($strings)
		{
			$stringArray = base64_encode(serialize($strings));
			$fileName = sha1($stringArray);
			$fullFileName = 'files/' . $fileName;
			if(!$fp = fopen("$fullFileName", "w"))
				$parent->badInput($this->errors->text("file", "write", ": $fileName"));
			if(!fputs($fp, $stringArray))
				$parent->badInput($this->errors->text("file", "write", ": $fileName"));
			fclose($fp);
// Write filename to session
			$this->session->setVar("import_fileNameStrings", $fileName);
		}
// Write unrecognised fields to session as serialised array
		$serArray = base64_encode(serialize($invalidFieldNames));
		$this->session->setVar("import_unrecognisedFields", $serArray);
// Create select boxes of all valid field names in WIKINDX including custom fields
		$possibleFields[0] = $this->messages->text('misc', 'ignore');
		foreach($map->types as $wkType => $bibtexType)
		{
			if(array_search($bibtexType, $inputTypes) === FALSE)
				continue;
			foreach($map->{$wkType}['possible'] as $field)
				$possibleFields[] = $field;
		}
		$possibleFields = array_unique($possibleFields);
// Get custom fields
		$recordset = $this->db->select(array("WKX_custom"), array('id', 'custom_label'));
		while($row = $this->db->loopRecordSet($recordset))
			$possibleFields[] = $row['id'] . '&nbsp;&nbsp;custom:&nbsp;&nbsp;' . $row['custom_label'];
		$pString = MISC::p($this->messages->text('import', 'invalidField1'));
		if(isset($vars['import_tag']) && $vars['import_tag'])
			$pString .= FORM::hidden('import_tag', $vars['import_tag']);
		if(isset($vars['import_groups']) && $vars['import_groups'])
			$pString .= FORM::hidden('import_groups', trim(implode(',', ($vars['import_groups']))));
		if(isset($vars['import_keywordSeparator']))
			$pString .= FORM::hidden('import_keywordSeparator', $vars['import_keywordSeparator']);
		if(isset($vars['import_titleSubtitleSeparator']))
			$pString .= FORM::hidden('import_titleSubtitleSeparator', $vars['import_titleSubtitleSeparator']);
		if(isset($vars['import_raw']) && $vars['import_raw'])
			$pString .= FORM::hidden('import_raw', $vars['import_raw']);
		if(isset($vars['import_importDuplicates']) && $vars['import_importDuplicates'])
			$pString .= FORM::hidden('import_importDuplicates', $vars['import_importDuplicates']);
		if(isset($vars['import_bib_ids']) && $vars['import_bib_ids'])
			$pString .= FORM::hidden('import_bib_ids', trim(implode(',', ($vars['import_bib_ids']))));
		foreach($invalidFieldNames as $invalidField)
			$pString .= MISC::p(FORM::selectFBox(MISC::b($invalidField), 
				'import_' . $invalidField, $possibleFields, 5));
		$pString .= MISC::p(FORM::checkbox($this->messages->text('import', 'invalidField2'), 
			"import_precedence"));
		$pString .= MISC::p(FORM::formSubmit());
		return $pString;
	}
/**
* stage3 - follows from prompting for field mapping
* 
* @author Mark Grimshaw
*/
	function stage3($vars, $parent)
	{
		$unrecognisedFields = 
			unserialize(base64_decode($this->session->getVar("import_unrecognisedFields")));
		$mapFields = $customFields = array();
		foreach($unrecognisedFields as $key)
		{
			$importKey = 'import_' . $key;
			if(($vars[$importKey] != $this->messages->text('misc', 'ignore')) && 
				(array_search($vars[$importKey], $mapFields) !== FALSE))
			{
				$this->session->setVar('importLock', FALSE);
				$this->session->clearArray("import");
				$parent->badInput($this->errors->text("file", "fieldMap"));
			}
			else if($vars[$importKey] != $this->messages->text('misc', 'ignore'))
				$mapFields[] = $vars[$importKey];
			if(array_key_exists($importKey, $vars) && 
				(sizeof($split = explode("custom:", 
				str_replace('&nbsp;&nbsp;', '', $vars[$importKey]))) == 2))
			{
				$customFields[$key] = $split[0];
				unset($vars[$importKey]);
			}
			else if(array_key_exists($importKey, $vars) && 
				($vars[$importKey] == $this->messages->text('misc', 'ignore')))
				unset($vars[$importKey]);
		}
		$file = 'files/' . $this->session->getVar('import_fileNameEntries');
		$entries = unserialize(base64_decode(file_get_contents($file)));
		if($this->session->getVar('import_fileNameStrings'))
		{
			$file = 'files/' . $this->session->getVar('import_fileNameStrings');
			$strings = unserialize(base64_decode(file_get_contents($file)));
		}
		else
			$strings = FALSE;
		return array($vars, $strings, $customFields, $entries, $unrecognisedFields);
	}
}
?>
